from app.models.order import Order, OrderStatus
from fastcrud import FastCRUD
from app.schemes.order import OrderCreate
from app.core.exceptions.http_exceptions import NotFoundException, BadRequestException
from app.util.pay.pay import alipay
from app.util.pay import settings
from app.core.pkg.log import logger
from app import config
from typing import Optional, Dict, Any
from datetime import datetime
import pytz
import json
from enum import Enum
from sqlalchemy import insert


order_service = FastCRUD(Order)


# 兼容不同版本的Pydantic
def model_to_dict(model) -> Dict[str, Any]:
    """将Pydantic模型转换为字典，兼容v1和v2版本"""
    if model is None:
        return {}
    if isinstance(model, dict):
        return model
    if hasattr(model, "model_dump"):
        # Pydantic v2
        return model.model_dump()
    elif hasattr(model, "dict"):
        # Pydantic v1
        return model.dict()
    else:
        # 回退方案：使用__dict__但要移除私有属性
        return {k: v for k, v in model.__dict__.items() if not k.startswith('_')}


# 确保对象是安全的纯字典形式，不包含复杂对象
def ensure_safe_dict(data: Dict[str, Any]) -> Dict[str, Any]:
    """将字典中的复杂对象转换为简单类型，确保可以安全序列化"""
    result = {}
    for key, value in data.items():
        # 处理枚举类型
        if isinstance(value, Enum):
            result[key] = str(value)
        # 处理日期时间类型
        elif isinstance(value, datetime):
            result[key] = value
        # 处理其他复杂对象
        elif hasattr(value, '__dict__'):
            result[key] = str(value)
        # 基本类型直接保留
        else:
            result[key] = value
    return result


class OrderService:
    def __init__(self, db):
        self.db = db
        self.order_service = order_service

    async def create_order(self, order: OrderCreate) -> Order:
        """
        创建订单
        
        Args:
            order: 订单创建对象
            
        Returns:
            Order: 创建的订单对象
            
        Raises:
            BadRequestException: 订单参数无效或创建失败
        """
        try:
            # 验证订单金额
            try:
                amount = float(order.order_amount)
                if amount <= 0:
                    logger.error(f"Invalid order amount in create_order: {amount}")
                    raise BadRequestException("订单金额必须大于0")
            except ValueError:
                logger.error(f"Invalid order amount format in create_order: {order.order_amount}")
                raise BadRequestException("订单金额格式不正确")
                
            # 创建订单对象 - 使用兼容的方法将模型转为字典
            order_data = model_to_dict(order)
            
            # 正确获取时区对象
            timezone_str = config.get("timezone", default='Asia/Shanghai')
            try:
                tz = pytz.timezone(timezone_str)
            except Exception:
                logger.warning(f"Invalid timezone: {timezone_str}, using default 'Asia/Shanghai'")
                tz = pytz.timezone('Asia/Shanghai')
                
            # 设置订单时间和状态
            now = datetime.now(tz)
            
            # 准备插入数据
            insert_data = {
                "payload_id": order_data["payload_id"],
                "order_trade_no": order_data["order_trade_no"],
                "order_amount": order_data["order_amount"],
                "description": order_data["description"],
                "order_status": OrderStatus.WAITING_PAY,  # 使用枚举值而不是字符串
                "order_time": now,
                "created_at": now,
                "is_deleted": False
            }
            
            logger.info(f"Creating order with trade_no: {order_data['order_trade_no']}")
            logger.debug(f"Order data before create: {insert_data}")
            
            try:
                # 使用原始SQL插入语句
                stmt = insert(Order).values(**insert_data)
                result = await self.db.execute(stmt)
                await self.db.commit()
                
                # 获取创建后的订单
                created_order = await self.order_service.get(self.db, order_trade_no=order_data["order_trade_no"])
                logger.info(f"Order created successfully: {order_data['order_trade_no']}")
                
                return created_order
            except Exception as db_err:
                await self.db.rollback()
                logger.error(f"Database error in create_order: {str(db_err)}")
                raise BadRequestException(f"数据库创建订单错误: {str(db_err)}")
        except Exception as e:
            logger.error(f"Error creating order: {str(e)}")
            if isinstance(e, BadRequestException):
                raise
            raise BadRequestException(f"创建订单失败: {str(e)}")

    async def create_pay_url(self, order_trade_no: str, payload_id: str) -> str:
        """
        创建支付链接
        
        Args:
            order_trade_no: 订单交易号
            payload_id: 用户ID
            
        Returns:
            str: 支付链接
            
        Raises:
            NotFoundException: 订单不存在
            BadRequestException: 订单参数无效或已支付
        """
        # 参数验证
        if not order_trade_no or not payload_id:
            logger.error(f"Invalid parameters: order_trade_no={order_trade_no}, payload_id={payload_id}")
            raise BadRequestException("订单号或用户ID无效")
            
        # 获取订单信息
        try:
            order = await self.order_service.get(self.db, order_trade_no=order_trade_no, payload_id=payload_id)
            if not order:
                logger.warning(f"Order not found: {order_trade_no} for user: {payload_id}")
                raise NotFoundException("订单不存在")
        except Exception as e:
            if isinstance(e, NotFoundException):
                raise
            logger.error(f"Error fetching order {order_trade_no}: {str(e)}")
            raise BadRequestException(f"获取订单信息失败: {str(e)}")
        
        # 检查订单状态，避免已支付订单重复创建支付链接
        if order.get("order_status") == OrderStatus.PAID:
            logger.warning(f"Order {order_trade_no} already paid, cannot create payment URL")
            raise BadRequestException("订单已支付，无法创建支付链接")
            
        # 订单金额验证
        try:
            order_amount = order.get("order_amount")
            amount = float(order_amount)
            if amount <= 0:
                logger.error(f"Invalid order amount: {amount}")
                raise BadRequestException("订单金额必须大于0")
        except (ValueError, TypeError):
            logger.error(f"Invalid order amount format: {order.get('order_amount')}")
            raise BadRequestException("订单金额格式不正确")
        
        # 获取回调URL，优先使用配置，否则使用默认值
        base_url = config.get("PAYMENT_CALLBACK_BASE_URL", default="http://localhost:9898")
        return_url = config.get("PAYMENT_CALLBACK_PATH", default="http://localhost:3000")

        logger.info(f"Creating payment URL for order: {order_trade_no}, amount: {order_amount}")
        
        try:
            # 创建支付宝交易付款链接
            out_trade_no = alipay.api_alipay_trade_page_pay(
                out_trade_no=order.get("order_trade_no"),  # 订单id
                total_amount=str(order.get("order_amount")),  # 订单总金额
                subject=order.get("description") or "命理定义积分购买",  # 付款标题信息
                return_url=return_url,  # 付款成功回调地址
                notify_url=f"{base_url}/api/v1/order/notify"  # 付款成功后异步通知地址
            )
            
            # 完整支付链接
            pay_url = f"{settings.GATEWAY}{out_trade_no}"
            logger.info(f"Payment URL created successfully for order: {order_trade_no}")
            
            return pay_url
        except Exception as e:
            logger.error(f"Error creating Alipay URL for order {order_trade_no}: {str(e)}")
            raise BadRequestException(f"创建支付链接失败: {str(e)}")
